﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Citi.Import.Util;
using System.Configuration;
using System.IO;
using Citi.EmailSender.Domain;
using Citi.EmailSender.ConsoleUI.EmailSenderWcf;

namespace Citi.EmailSender.ConsoleUI
{
    public class EmailTxtData
    {
        private static string TxtEmailFile { get { return ConfigurationManager.AppSettings["TxtEmailFile"]; } }

        public string ApplicationName { get; set; }
        public string To { get; set; }
        public string Cc { get; set; }
        public string Bcc { get; set; }
        public string Subject { get; set; }
        public string SentOnBehalfOfName { get; set; }
        public string BodyMessage { get; set; }
        public int TemplateId { get; set; }
        public string Url { get; set; }
        public string Parameters { get; set; }
        public DateTime? ScheduleDateTime { get; set; }
        public bool? NeedApprovalToSend { get; set; }
        public string Approvers { get; set; }

        private const string ApplicationNameColumn = "ApplicationName";
        private const string ToColumn = "To";
        private const string CcColumn = "Cc";
        private const string BccColumn = "Bcc";
        private const string SubjectColumn = "Subject";
        private const string SentOnBehalfOfNameColumn = "SentOnBehalfOfName";
        private const string BodyMessageColumn = "BodyMessage";
        private const string TemplateIdColumn = "TemplateId";
        private const string UrlColumn = "Url";
        private const string ParametersColumn = "Parameters";
        private const string ScheduleDateTimeColumn = "ScheduleDateTime";
        private const string NeedApprovalToSendColumn = "NeedApprovalToSend";
        private const string ApproversColumn = "Approvers";

        private static readonly List<Definition<EmailTxtData>> Definitions = new List<Definition<EmailTxtData>>
            {
                new Definition<EmailTxtData> { ModelProperty = x => x.ApplicationName, Required = true, ColumnName = ApplicationNameColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.SentOnBehalfOfName, Required = true, ColumnName = SentOnBehalfOfNameColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.To, ColumnName = ToColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Cc, ColumnName = CcColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Bcc, ColumnName = BccColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Subject,  ColumnName = SubjectColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.BodyMessage, ColumnName = BodyMessageColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.TemplateId, ColumnName = TemplateIdColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Url, ColumnName = UrlColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Parameters, ColumnName = ParametersColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.ScheduleDateTime, ColumnName = ScheduleDateTimeColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.NeedApprovalToSend, ColumnName = NeedApprovalToSendColumn},
                new Definition<EmailTxtData> { ModelProperty = x => x.Approvers,  ColumnName = ApproversColumn}
            };

        public static void ImportEmails()
        {
            const string header = "ApplicationName|To|Cc|Bcc|Subject|SentOnBehalfOfName|BodyMessage|TemplateId|Url|Parameters|ScheduleDateTime|NeedApprovalToSend|Approvers";

            List<Error> errors = null;
            var emails = Conversion.ConvertFromTxt(Definitions, TxtEmailFile, '|', ref errors);

            File.WriteAllText(TxtEmailFile, header);

            Console.WriteLine("{0} {1} emails found", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), emails.Count());

            if (errors != null && errors.Any())
                errors.ForEach(x => Console.WriteLine("{0} An error was found at line {1}. Error: {2}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), x.Line, x.ErrorDescription));

            if (!emails.Any()) return;

            using (var client = new EmailClient())
            {
                foreach (var email in emails)
                {
                    var index = emails.IndexOf(email) + 1;

                    try
                    {
                        Console.WriteLine("{0] #{1}: Inserting email", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), index);
                        client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

                        var domain = new EmailSenderWcf.Email
                        {
                            BodyMessage = email.BodyMessage,
                            Subject = email.Subject,
                            SentOnBehalfOfName = email.SentOnBehalfOfName,
                            To = FillAddress(email.To),
                            Bcc = FillAddress(email.Bcc),
                            Cc = FillAddress(email.Cc),
                            ApplicationName = email.ApplicationName,
                            Url = email.Url,
                            Parameters = FillParameters(email.Parameters),
                            Importance = Enums.EmailImportance.Normal,
                            NeedApprovalToSend = email.NeedApprovalToSend,
                            ScheduleDateTime = email.ScheduleDateTime,
                            TemplateId = email.TemplateId
                        };

                        client.InsertEmailInQueue(domain);
                        Console.WriteLine("{0} #{1}: Inserted on queue", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), index);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("{0} #{1}: Error {2}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), index, e.Message);
                        continue;
                    }
                }
            }
        }

        private static List<EmailSenderWcf.EmailAddress> FillAddress(string addresses)
        {
            if (string.IsNullOrWhiteSpace(addresses)) return null;

            return addresses.Split(';').Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList();
        }

        private static Dictionary<string, string> FillParameters(string parameters)
        {
            var dictionary = new Dictionary<string, string>();

            if (string.IsNullOrWhiteSpace(parameters)) return dictionary;

            foreach (var parameter in parameters.Split(';'))
            {
                var values = parameters.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                dictionary.Add(values[0], values[1]);
            }

            return dictionary;
        }
    }
}
